package com.gitee.hermer.engine.jars.core.loader.event.listener;

import java.io.File;
import java.util.Date;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.gitee.hermer.boot.jee.commons.utils.DateUtils;
import com.gitee.hermer.boot.jee.commons.verify.Assert;
import com.gitee.hermer.engine.jars.app.sdk.EngineAppClassLoader;
import com.gitee.hermer.engine.jars.core.app.domain.EngineAppJobContext;
import com.gitee.hermer.engine.jars.core.context.IEngineAppContext;
import com.gitee.hermer.engine.jars.core.context.domain.EngineAppContext;
import com.gitee.hermer.engine.jars.core.context.impl.EngineAppContextImpl.EngineAppLoaderState;
import com.gitee.hermer.engine.jars.core.event.listener.EngineEventListener;
import com.gitee.hermer.engine.jars.core.execute.EngineExecuteCallable;
import com.gitee.hermer.engine.jars.core.execute.EngineExecuteRunnable;
import com.gitee.hermer.engine.jars.core.execute.EngineExecuteThread.LifeCycle;
import com.gitee.hermer.engine.jars.core.execute.manage.IEngineExecutePoolManager;
import com.gitee.hermer.engine.jars.core.loader.EngineAppBeanScanner;
import com.gitee.hermer.engine.jars.core.loader.event.EngineAppInitializationEvent;
import com.gitee.hermer.engine.jars.core.loader.release.IReleaseHandle;
import com.gitee.hermer.engine.jars.starter.thread.pool.callback.CallableResult;

@Component
public class EngineInitializationEventListener extends EngineEventListener<EngineAppInitializationEvent>{

	@Autowired
	private IEngineExecutePoolManager executePoolManager;

	@Autowired
	private IEngineAppContext engineAppContext;

	@Autowired
	private EngineAppBeanScanner scanner;
	
	@Autowired
	private IReleaseHandle[] handles;

	private ApplicationContext parentContext;

	@Override
	public void onEvent(EngineAppInitializationEvent event) {
		try{
			executePoolManager.executeAsyn(new EngineExecuteCallable<Boolean>(parentContext,event.getCacheKey(),LifeCycle.INITIALIZATION) {

				@Override
				public Boolean onExecute() {
					try{
						File jarFile = (File) event.getSource();
						engineAppContext.updateEngineAppLoaderState(cacheKey,  EngineAppLoaderState.BEGIN_INIT);
						info("线程ID[%s]|线程名[%s]|项目[%s]|容器路径[%s]|初始化中...",this.getId(),this.getName(),event.getCacheKey(),jarFile.getPath());
						this.classLoader = scanner.getClassLoader(jarFile,parentContext.getClassLoader(),event.getCacheKey());
						context = scanner.springClassLoader((EngineAppClassLoader)this.classLoader);
						Assert.notNull(context);
						info("线程ID[%s]|线程名[%s]|项目[%s]|容器初始化完毕！",getId(),getName(),event.getCacheKey());
						engineAppContext.updateEngineAppLoaderState(cacheKey,  EngineAppLoaderState.END_INIT);
						engineAppContext.updateEngineAppLoaderState(cacheKey,  EngineAppLoaderState.RUN_ING);
						engineAppContext.register(cacheKey, new EngineAppContext(
								cacheKey, jarFile.getName(), event.getFileMd5(), DateUtils.getDateTimeFormat(new Date(jarFile.lastModified())), 
								context, parentContext, new EngineExecuteRunnable(new EngineAppJobContext(context, parentContext),cacheKey,null,LifeCycle.DESTROY) {
									
									@Override
									public Object onExecute() {
										for (IReleaseHandle iReleaseHandle : handles) {
											iReleaseHandle.release(this);
										}
										return null;
									}
								}));
						return true;
						
					}catch (Throwable e) {
						error(e.getMessage(),e);
					}
					return false;
				}
			},new CallableResult<Boolean>(){
				@Override
				public void onCall(Boolean value) throws Exception {
					
				}
			});
		}catch (Throwable e) {
			error(e.getMessage(),e);
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.parentContext = applicationContext;
	}

}
